package main;

import java.util.Stack;

//Nikolas Wolfe
//2/9/2009
//CIS 4930
//Towers of Hanoi

/*
 * This is a wrapper / accessor class for a Tower of disks
 * maintains a reference to the adjacent towers in the set
 */

public class HanoiTower 
{
	private HanoiTower rightTower;
	private HanoiTower leftTower;
	private String name;
	
	private boolean readyToYield = false;
	private int diskCount = 0;
	private Stack<Disk> tower = new Stack<Disk>();
	
	public HanoiTower(Integer numDisks, String name)
	{
		// fill current Tower
		int i; 
		if(numDisks != null && numDisks >= 1){ 
			i = numDisks;
			diskCount = numDisks;
		} else {
			i = 0;
		}
		while(i > 0)
		{
			Disk disk = new Disk(i);
			disk.setPrevDisk(null);
			disk.setPrevTower(this);
			if( !tower.isEmpty() )
			{
				disk.setPrevDisk(tower.peek());
			}
			tower.push(disk);
			--i;
		}
		// set name
		this.name = name;
	}

	// push a disk on a tower
	public synchronized boolean pushDisk(Disk disk)
	{
		// check the top disk on the stack
		if( tower.isEmpty() )
		{
			tower.push(disk);
			++diskCount;
			return true;
		}
		if( disk.getValue() < tower.peek().getValue() )
		{
			tower.push(disk);
			++diskCount;
			return true;
		}
		else { return false; }
	}
	
	// take a disk off a tower
	public synchronized Disk popDisk()
	{
		if( !isEmpty() )
		{
			--diskCount;
			return tower.pop();
		}
		else{ return null; }
	}
	
	public int getDiskCount()
	{
		return diskCount;
	}
	
	public boolean isEmpty()
	{
		return tower.isEmpty();
	}
	
	public String getName()
	{
		return name;
	}
	
	// get the value of the disk on the top on the stack
	public synchronized int peekTowerValue()
	{
		if( !tower.isEmpty() )
		{
			return tower.peek().getValue();
		} else return 0;
	}
	
	// may return null! Only call this when you must modify
	// the disk's properties
	public Disk peekTower()
	{ 
		if( !tower.isEmpty() )
		{
			return tower.peek();
		}
		else{ return null; }
	}

	public String toString()
	{
		String output = "";
		Stack<Disk> temp = new Stack<Disk>();
		
		while(!tower.isEmpty()){
			output += tower.peek().getValue();
			temp.push(tower.pop());
		}
		while(!temp.isEmpty()){ tower.push(temp.pop()); }
		return output;
	}
	
	/*  --------------------------
	 *  Adjacency getters/setters
	 *  -------------------------
	 */
	public HanoiTower getRightTower()
	{
		return rightTower;
	}

	public void setRightTower(HanoiTower rightTower)
	{
		this.rightTower = rightTower;
	}

	public HanoiTower getLeftTower()
	{
		return leftTower;
	}

	public void setLeftTower(HanoiTower leftTower)
	{
		this.leftTower = leftTower;
	}
	
	/*
	 * -----------------------
	 *  Yield getters/setters
	 * -----------------------
	 */
	public synchronized boolean isReadyToYield()
	{
		// if this is ready to yield, we reset it and return true
		if( readyToYield )
		{
			this.readyToYield = false;
			return true;
		}
		else { return readyToYield; }
	}

	public synchronized void setReadyToYield(boolean readyToYield)
	{
		this.readyToYield = readyToYield;
	}
}
